﻿using System;
using System.Security.Cryptography;
using System.Text;

namespace DotnetApp.Security
{
    public class AesTextProtector : ITextProtector
    {
        public string Encrypt(string plainText, string password)
        {
            // Default:  

            if (plainText == null)
            {
                throw new ArgumentNullException(nameof(plainText));
            }

            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            if (password.Length != 32)
            {
                throw new ArgumentOutOfRangeException(nameof(password), "Length of password must be 32.");
            }

            using var aes = CreateAes(password);
            using var cryptTransform = aes.CreateEncryptor();
            var plainBytes = Encoding.UTF8.GetBytes(plainText);
            var cipherText = cryptTransform.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
            return Convert.ToBase64String(cipherText);
        }

        public string Decrypt(string encryptedText, string password)
        {
            if (encryptedText == null)
            {
                throw new ArgumentNullException(nameof(encryptedText));
            }

            if (password == null)
            {
                throw new ArgumentNullException(nameof(password));
            }

            if (password.Length != 32)
            {
                throw new ArgumentOutOfRangeException(nameof(password), "Length of password must be 32.");
            }

            using var aes = CreateAes(password);
            using var cryptTransform = aes.CreateDecryptor();
            var encryptedBytes = Convert.FromBase64String(encryptedText);
            var plainBytes = cryptTransform.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
            return Encoding.UTF8.GetString(plainBytes);
        }

        private static Aes CreateAes(string password)
        {
            var aes = Aes.Create();
            var keys = Encoding.UTF8.GetBytes(password);
            aes.Key = keys;
            aes.IV = keys.AsSpan().Slice(0, 16).ToArray();
            return aes;
        }
    }
}